import ply.lex as lex
import sys
#from  symbolTable import *

#reserved words
res = (
	'FALSE',
	'FOR',
	'FUNCTION',
	'IF',
	'NEW',
	'RETURN',
	'THIS',
	'TRUE',
	'VAR',
	'WHILE',
	'WITH',
	'PROMPT',
	'DOCUMENT',
	'WRITE'
	)

reserved = {}
for r in res:
	reserved[r.lower()] = r

tokens = reserved.values()
tokens += [
		    'TYPEID',
		    'NUMBER',
		    'CCONST',
		    'STRING',
		    'PLUS',
		    'MINUS',
		    'TIMES',
		    'AND',
		    'LT',
		    'LE',
		    'EQ',
		    'ASSIGN',
		    'CONDOP',
		    'LPAREN',
		    'RPAREN',
		    'LBRACE',
		    'RBRACE',
		    'COMMA',
		    'PERIOD',
		    'SEMI',
		    'COLON',
		    'NLINE',
		    'ID'
		]

#  ---------------------------------------------------------------
#SIMPLE RULES
#  ---------------------------------------------------------------

#t_ignore = r' '

t_PLUS             = r'\+'
t_MINUS            = r'-'
t_TIMES            = r'\*'
t_AND              = r'&&'
t_EQ               = r'=='
t_LT		   = r'<'
t_ASSIGN           = r'='
t_CONDOP           = r'\?'
t_LPAREN           = r'\('
t_RPAREN           = r'\)'
t_LBRACE           = r'\{'
t_RBRACE           = r'\}'
t_COMMA            = r','
t_PERIOD           = r'\.'
t_SEMI             = r';'
t_COLON            = r':'

#t_FCONST = r'((\d+)(\.\d+)(e(\+|-)?(\d+))? | (\d+)e(\+|-)?(\d+))([lL]|[fF])?'
t_CCONST = r'(L)?\'([^\\\n]|(\\.))*?\'' # for comments



	
#  ---------------------------------------------------------------
#  COMPLEX TOKENS
#  ---------------------------------------------------------------


def t_NUMBER (t):
	r'\d+'
	try:
	    t.value = int(t.value)
	except:
		print 'ERROR : Linea: %d Numero: %s es demasiado largo'%(t.lexer.lineno,t.value)
		t.value = 0
		sys.exit()
	if (t.value > 32767):
		print 'ERROR : Linea: %d Numero: %s es demasiado largo'%(t.lexer.lineno,t.value)
		t.value = 0
		sys.exit()
	return t 


def t_STRING (t): 
	r'\"([^\\\n]|(\\.))*?\"'
	t.value = t.value[1:-1] #el valor del string no tiene las comillas
	return t

def t_newline(t):
	r'\n+'
	t.lexer.lineno += len(t.value)
	t.type = 'NLINE'
	return t

def t_malformed_fnumber(t):
	r'(0\d+)((\.\d+(e[+-]?\d+)?)|(e[+-]?\d+))'
	print "Linea %d. Numero en coma flotante mal formado '%s'" % (t.lexer.lineno, t.value)


def t_malformed_inumber(t):
	r'0\d+'
	print "Linea %d. Entero mal formado '%s'" % (t.lexer.lineno, t.value)



def t_ID(t):
	r'_*[a-zA-Z][a-zA-Z_\d]*'
	t.type = reserved.get(t.value,"ID")
#	if (t.type  == 'ID'): #si no es un identifcador es que es una palabra reservada
#	       print "HAY que poner value la pos pero hecho por el sintactico"
	       #t.value = self.st.insert(t.value)
	return t

def t_COMMENT(t):
	r'(/\*(.|\n)*?\*/)\n|//[^\n]*\n'
	t.lexer.lineno += t.value.count('\n')
	#TODO aumentar el valor de lineno como global en lexer
        #pass



#  ---------------------------------------------------------------
#  IGNORED TOKENS
#  ---------------------------------------------------------------

def t_WHITESPACE(t):
        r'[ \t]+'
        pass

#  ---------------------------------------------------------------
#  ERROR HANDLING
#  ---------------------------------------------------------------

def t_error(t):
        print "Line %d." % (t.lineno,) + "",
        if t.value[0] == '"':
            print "Literal no terminado."
            if t.value.count('\n') > 0:
                t.skip(t.value.index('\n'))
        elif t.value[0:2] == '/*':
            print "Comentario sin cerrar."
        else:
            print "Caracter ilegal '%s'" % t.value[0]
            t.lineno += 1

lex.lex()



## Test it output
def test(filename):
	file = open(filename)
	lines = file.read()
	file.close()
	lex.input(lines)
	while 1:
		tok = lex.token()
		if not tok: break
		print tok

#def testFromLine(self,line):
#	self.lexer.input(line)
#	while 1:
#		tok = lex.token()
#		if not tok: break
#		print tok
